babl-cache: store reference fishes in the cache
authorEll <ell_se@yahoo.com>
Sat, 4 Aug 2018 06:18:37 +0000 (02:18 -0400)
committerEll <ell_se@yahoo.com>
Sat, 4 Aug 2018 07:02:59 +0000 (03:02 -0400)
When we only have a reference fish for a given conversion, and not
a path fish, store a corresponding entry in the cache, marked by a
"[reference]" tag in the fish's attributes line, and containing no
conversion list.  When reloading the cache, make sure a reference
fish is created for the conversion without trying to construct a
path fish, so that we don't waste time trying to search for a
conversion path.

Note that we still show a "missing fast path" warning, even for
cached reference fishes.

babl/babl-cache.c
babl/babl-fish-path.c
babl/babl-fish.c
babl/babl-internal.h

index e85216e649fc6ee26eed72b6a5e261d11c5205a2..48e359ccc0726c13dc7694780bd9a17387274950 100644 (file)
@@ -108,8 +108,11 @@ static char *
 babl_fish_serialize (Babl *fish, char *dest, int n)
 {
   char *d = dest;
-  if (fish->class_type != BABL_FISH_PATH)
+  if (fish->class_type != BABL_FISH &&
+      fish->class_type != BABL_FISH_PATH)
+  {
     return NULL;
+  }
 
   snprintf (d, n, "%s\n%s\n",
   babl_get_name (fish->fish.source),
@@ -119,20 +122,32 @@ babl_fish_serialize (Babl *fish, char *dest, int n)
   snprintf (d, n, "\tpixels=%li", fish->fish.pixels);
   n -= strlen (d);d += strlen (d);
 
-  snprintf (d, n, " cost=%d", (int)fish->fish_path.cost);
-  n -= strlen (d);d += strlen (d);
+  if (fish->class_type == BABL_FISH_PATH)
+  {
+    snprintf (d, n, " cost=%d", (int)fish->fish_path.cost);
+    n -= strlen (d);d += strlen (d);
+  }
 
   snprintf (d, n, " error=%f", fish->fish.error);
   n -= strlen (d);d += strlen (d);
 
+  if (fish->class_type == BABL_FISH)
+  {
+    snprintf (d, n, " [reference]");
+    n -= strlen (d);d += strlen (d);
+  }
+
   snprintf (d, n, "\n");
   n -= strlen (d);d += strlen (d);
 
-  for (int i = 0; i < fish->fish_path.conversion_list->count; i++)
+  if (fish->class_type == BABL_FISH_PATH)
   {
-    snprintf (d, n, "\t%s\n",
-      babl_get_name(fish->fish_path.conversion_list->items[i]  ));
-    n -= strlen (d);d += strlen (d);
+    for (int i = 0; i < fish->fish_path.conversion_list->count; i++)
+    {
+      snprintf (d, n, "\t%s\n",
+        babl_get_name(fish->fish_path.conversion_list->items[i]  ));
+      n -= strlen (d);d += strlen (d);
+    }
   }
 
   return dest;
@@ -278,19 +293,45 @@ void babl_init_db (void)
               return;
             }
 
-            babl = babl_calloc (1, sizeof (BablFishPath) +
-                                strlen (name) + 1);
-            babl_set_destructor (babl, _babl_fish_path_destroy);
-
-            babl->class_type     = BABL_FISH_PATH;
-            babl->instance.id    = babl_fish_get_id (from_format, to_format);
-            babl->instance.name  = ((char *) babl) + sizeof (BablFishPath);
-            strcpy (babl->instance.name, name);
-            babl->fish.source               = from_format;
-            babl->fish.destination          = to_format;
-            babl->fish_path.conversion_list = babl_list_init_with_size (10);
-            _babl_fish_prepare_bpp (babl);
-            _babl_fish_rig_dispatch (babl);
+            if (strstr (token, "[reference]"))
+            {
+              /* there isn't a suitable path for requested formats,
+               * let's create a dummy BABL_FISH instance and insert
+               * it into the fish database to indicate that such path
+               * does not exist.
+               */
+              const char *name = "X"; /* name does not matter */
+              babl = babl_calloc (1, sizeof (BablFish) + strlen (name) + 1);
+
+              babl->class_type       = BABL_FISH;
+              babl->instance.id      = babl_fish_get_id (from_format,
+                                                         to_format);
+              babl->instance.name    = ((char *) babl) + sizeof (BablFish);
+              strcpy (babl->instance.name, name);
+              babl->fish.source      = from_format;
+              babl->fish.destination = to_format;
+              babl->fish.data        = (void*) 1; /* signals babl_fish() to
+                                                   * show a "missing fash path"
+                                                   * warning upon the first
+                                                   * lookup
+                                                   */
+            }
+            else
+            {
+              babl = babl_calloc (1, sizeof (BablFishPath) +
+                                  strlen (name) + 1);
+              babl_set_destructor (babl, _babl_fish_path_destroy);
+
+              babl->class_type     = BABL_FISH_PATH;
+              babl->instance.id    = babl_fish_get_id (from_format, to_format);
+              babl->instance.name  = ((char *) babl) + sizeof (BablFishPath);
+              strcpy (babl->instance.name, name);
+              babl->fish.source               = from_format;
+              babl->fish.destination          = to_format;
+              babl->fish_path.conversion_list = babl_list_init_with_size (10);
+              _babl_fish_prepare_bpp (babl);
+              _babl_fish_rig_dispatch (babl);
+            }
 
             token2 = strtok_r (&token[1], seps2, &tokp2);
             while( token2 != NULL )
@@ -301,7 +342,8 @@ void babl_init_db (void)
               }
               else if (!strncmp (token2, "cost=", 5))
               {
-                babl->fish_path.cost = babl_parse_double (token2 + 5);
+                if (babl->class_type == BABL_FISH_PATH)
+                  babl->fish_path.cost = babl_parse_double (token2 + 5);
               }
               else if (!strncmp (token2, "pixels=", 7))
               {
@@ -310,7 +352,7 @@ void babl_init_db (void)
               token2 = strtok_r (NULL, seps2, &tokp2);
             }
           }
-          else if (to_format && babl)
+          else if (to_format && babl && babl->class_type == BABL_FISH_PATH)
           {
             Babl *conv = (void*)babl_db_find(babl_conversion_db(), &token[1]);
             if (!conv)
index 30c4a68bf8c94d118ce72e6d51ec03204a0d5a0f..2e87268109763825cc1ccb6164478b91ffd6a00a 100644 (file)
@@ -464,6 +464,34 @@ _babl_fish_prepare_bpp (Babl *babl)
      }
 }
 
+void
+_babl_fish_missing_fast_path_warning (const Babl *source,
+                                      const Babl *destination)
+{
+#ifndef BABL_UNSTABLE
+  if (debug_conversions)
+#endif
+  {
+    static int warnings = 0;
+
+    if (_babl_legal_error() <= 0.0000000001)
+      return;
+
+    if (warnings++ == 0)
+      fprintf (stderr,
+"Missing fast-path babl conversion detected, Implementing missing babl fast paths\n"
+"accelerates GEGL, GIMP and other software using babl, warnings are printed on\n"
+"first occurance of formats used where a conversion has to be synthesized\n"
+"programmatically by babl based on format description\n"
+"\n");
+
+    fprintf (stderr, "*WARNING* missing babl fast path(s): \"%s\" to \"%s\"\n",
+       babl_get_name (source),
+       babl_get_name (destination));
+
+  }
+}
+
 
 static Babl *
 babl_fish_path2 (const Babl *source,
@@ -599,28 +627,8 @@ babl_fish_path2 (const Babl *source,
       babl_free (babl);
       babl_mutex_unlock (babl_format_mutex);
 
-#ifndef BABL_UNSTABLE
-      if (debug_conversions)
-#endif
-      {
-        static int warnings = 0;
-
-        if (_babl_legal_error() <= 0.0000000001)
-            return NULL;
+      _babl_fish_missing_fast_path_warning (source, destination);
 
-        if (warnings++ == 0)
-          fprintf (stderr,
-"Missing fast-path babl conversion detected, Implementing missing babl fast paths\n"
-"accelerates GEGL, GIMP and other software using babl, warnings are printed on\n"
-"first occurance of formats used where a conversion has to be synthesized\n"
-"programmatically by babl based on format description\n"
-"\n");
-
-        fprintf (stderr, "*WARNING* missing babl fast path(s): \"%s\" to \"%s\"\n",
-           babl_get_name (source),
-           babl_get_name (destination));
-
-      }
       return NULL;
     }
 
index 8d31e1b76d3b15524a1fcda0f6a3c98dc862b109..a1baa5061778952eebf494b042de8f4378970ddc 100644 (file)
@@ -290,6 +290,16 @@ babl_fish (const void *source,
               }
 #endif
           }
+        else if (ffish.fish_fish->fish.data)
+          {
+            /* the dummy fish was created by the cache, and we need to manually
+             * show a "missing fast path" warning for it on the first lookup.
+             */
+            _babl_fish_missing_fast_path_warning (ffish.fish_fish->fish.source,
+                                                  ffish.fish_fish->fish.destination);
+
+            ffish.fish_fish->fish.data = NULL;
+          }
       }
 
     if (ffish.fish_ref)
index a6f11968e307ef8088579fad98576de3dd6292b7..0f8a07c69d065db2058714c2cf9a312ca04d9c0f 100644 (file)
@@ -427,6 +427,8 @@ babl_conversion_process (const Babl *babl,
   conversion->dispatch (babl, source, destination, n, conversion->data);
 }
 
+void _babl_fish_missing_fast_path_warning (const Babl *source,
+                                           const Babl *destination);
 void _babl_fish_rig_dispatch (Babl *babl);
 void _babl_fish_prepare_bpp (Babl *babl);